#include <iostream>
#include <string>
#include "zmq.hpp"
#include "json.h"

using namespace std;

void send_command(zmq::socket_t& command_channel, string str) // Performs command sending
{
	// Send command
	zmq::message_t command(str.size()); // Create a message container with appropriate size
	memcpy((void *)command.data(), str.c_str(), str.size()); // Fill message container with string
	command_channel.send(command); // Send command
}

json::Object receive_response(zmq::socket_t& command_channel)
{
	// Initialize variables
	string str;

	// Receive response
	zmq::message_t reply; // Create a message container
	command_channel.recv(&reply); // Receive message and store in container
	str = string((char*)(reply.data()), reply.size()); // Convert message to string

	// Convert response into data
	json::Object obj; // Create data container
	obj = json::Deserialize(str); // Convert message into data and store in container

	// Return data
	return obj;
}

void wait_for_response(zmq::socket_t& command_channel)
{
	// Receive response
	zmq::message_t reply; // Create a message container
	command_channel.recv(&reply); // Receive message and store in container
	string str = string((char*)(reply.data()), reply.size());
}

string prompt_for_server_ip()
{
	//Initilize variables
	string address;

	// Prompt user for server address
	cout << "Server address: ";
	cin >> address;
	//address = "ip-10-234-167-219.ec2.internal";
	return address;
}

string prompt_for_match_token()
{
	//Initilize variables
	string match_token;

	// Prompt user for match token
	cout << "Match Token: ";
	cin >> match_token;
	//match_token = "7d5cdb0a-2850-4f32-8747-9eeec9b607ae";
	return match_token;
}

void connect_to_server(zmq::socket_t& command_channel, zmq::socket_t& state_channel, string match_token, string ip)
{
	// Connect to the command channel
	string ip1 = "tcp://" + ip + ":5557";
	cout << "Connecting to command channel at: " << ip1 << "\n";
	command_channel.connect(ip1.c_str());

	// Connect to the state channel
	ip1 = "tcp://" + ip + ":5556";
	cout << "Connecting to state channel at: " << ip1 << "\n";
	state_channel.connect(ip1.c_str());
	state_channel.setsockopt(ZMQ_SUBSCRIBE, match_token.c_str(), strlen(match_token.c_str()));

	// Build JSON command message
	json::Object obj; // Create a data container
	obj["comm_type"] = "MatchConnect";
	obj["match_token"] = match_token;
	obj["team_name"] = "Chicken Wing Wednesdays";
	obj["password"] = "1013488610127028";
	string str = json::Serialize(obj); // Turn the container into a string

	// Log in to the battle
	cout << "Sending Match Connect message...\n";
	send_command(command_channel, str);
}

string receive_client_token(zmq::socket_t& command_channel)
{
	// Initialize variables
	string client_token;

	// Receive data
	json::Object obj; // Create a data container
	obj = receive_response(command_channel); // Receive data and store in container

	// Search data for client token
	client_token = obj["client_token"];

	// Log client token
	cout << "Client Token: " << client_token << "\n";

	return client_token;
}

json::Object update_game_state(zmq::socket_t& state_channel)
{
	// Initialize variables
	string str;

	// Receive game state message
	zmq::message_t update; // Create a message container
	state_channel.recv(&update); // Contains the filter, this is junk
	state_channel.recv(&update); // Receive game state message and store in container
	str = string((char*)(update.data()), update.size()); // Convert message into a string

	// Convert game state message into data
	json::Object obj; // Create data container
	obj = json::Deserialize(str); // Convert message into data and store in container

	// Return the data
	return obj;
}